﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HP.Cachalote.Services.Interfaces;
using HP.Cachalote.DataModels;
using HP.Cachalote.Repositories.Interfaces;
using System.Linq.Expressions;

namespace HP.Cachalote.UnitTests.FakeServices
{
    public class FakeServiceBase<T> : IService<T> where T : DataModelBase
    {
        protected IRepositoryFactory RepositoryFactory;
        protected IDataValidator<T> EntityValidator;

        /// <summary>
        /// Just need to make sure every sub-class has a contructor accpets IRepositoryFactory parameter.
        /// </summary>
        /// <param name="session">An instance implements IRepositoryFactory.</param>
        public FakeServiceBase(IRepositoryFactory repositoryFactory, IDataValidator<T> entityValidator)
        {
            RepositoryFactory = repositoryFactory;
            EntityValidator = entityValidator;
        }

        /// <summary>
        /// Add new entity.
        /// </summary>
        /// <param name="entity">The new entity will be added into database.</param>
        /// <returns>The id of the new added entity.</returns>
        public virtual object Add(T entity)
        {
            return RepositoryFactory.CreateRepositoryBase<T>().Add(entity);
        }

        // <summary>
        /// Get entity by id.
        /// </summary>
        /// <param name="id">The specified id.</param>
        /// <returns>The matched data.</returns>
        public virtual T Get(object id)
        {
            return RepositoryFactory.CreateRepositoryBase<T>().Get(id);
        }

        /// <summary>
        /// Filter data by lambda expression.
        /// </summary>
        /// <param name="expression">The lambda expression that accepts TDataModel and return boolean.</param>
        /// <returns>An IList list of data.</returns>
        public virtual IList<T> Filter(Expression<Func<T, bool>> expression)
        {
            IRepository<T> r = RepositoryFactory.CreateRepositoryBase<T>();
            var v1 = r.Filter(expression);

            if (v1 == null)
            {
                return null;
            }

            var v2 = v1.ToList();
            return v2;
        }

        /// <summary>
        /// Get all data. You also can filter the data later since the returned result is a IList collection.
        /// </summary>
        /// <returns>An IList collection of data.</returns>
        public virtual IList<T> GetAll()
        {
            return RepositoryFactory.CreateRepositoryBase<T>().GetAll().ToList();
        }

        /// <summary>
        /// Get the data's count by using provided lambda expression.
        /// </summary>
        /// <param name="expression">The lambda expression that accepts T and return boolean.</param>
        /// <returns>The data's count.</returns>
        public int GetRowCount(Expression<Func<T, bool>> expression)
        {
            return RepositoryFactory.CreateRepositoryBase<T>().GetRowCount(expression);
        }

        /// <summary>
        /// Update existing entity.
        /// </summary>
        /// <param name="entity">The entity will be updated.</param>
        public virtual void Update(T entity)
        {
            RepositoryFactory.CreateRepositoryBase<T>().Update(entity);
        }

        /// <summary>
        /// Add or update entity.
        /// </summary>
        /// <param name="data">The entity will be updated if it is existing or added if it cannot be found.</param>
        public virtual void AddOrUpdate(T entity)
        {
            RepositoryFactory.CreateRepositoryBase<T>().AddOrUpdate(entity);
        }

        /// <summary>
        /// Delete the specified entity.
        /// </summary>
        /// <param name="entity">The entity will be deleted from database.</param>
        public virtual void Delete(T entity)
        {
            RepositoryFactory.CreateRepositoryBase<T>().Delete(entity);
        }
    }
}